home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue70 / alfresco / AAStrms.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-05-08  |  19.9 KB  |  684 lines

  1. {*********************************************************}
  2. {* AAStrms                                               *}
  3. {* Copyright (c) Julian M Bucknall 2001                  *}
  4. {* All rights reserved.                                  *}
  5. {*********************************************************}
  6. {* Algorithms Alfresco: Streams and filters              *}
  7. {*********************************************************}
  8.  
  9. {Note: this unit is released as freeware. In other words, you are free
  10.        to use this unit in your own applications, however I retain all
  11.        copyright to the code. JMB}
  12.  
  13. unit AAStrms;
  14.  
  15. interface
  16.  
  17. uses
  18.   SysUtils,
  19.   Classes,
  20.   AAStrBld,
  21.   AARegex;
  22.  
  23. type
  24.   TaaFileStream = class(TFileStream)
  25.     {a file stream that remembers its name}
  26.     private
  27.       FName : string;
  28.     protected
  29.     public
  30.       constructor Create(const aFileName : string; aMode : word);
  31.       property Name : string read FName;
  32.   end;
  33.  
  34.   TaaReadFilter = class(TStream)
  35.     {a read-only filter}
  36.     private
  37.       FSize       : longint;
  38.       FStream     : TStream;
  39.       FGotSizeReq : boolean;
  40.     protected
  41.     public
  42.       constructor Create(aStream : TStream; aSize : longint);
  43.  
  44.       function Read(var Buffer; Count : longint) : longint; override;
  45.       function Seek(Offset : longint; Origin : word) : longint; override;
  46.       function Write(const Buffer; Count : longint) : longint; override;
  47.   end;
  48.  
  49.   TaaWriteFilter = class(TStream)
  50.     {a write-only filter}
  51.     private
  52.       FSize       : longint;
  53.       FStream     : TStream;
  54.       FGotSizeReq : boolean;
  55.     protected
  56.     public
  57.       constructor Create(aStream : TStream);
  58.  
  59.       function Read(var Buffer; Count : longint) : longint; override;
  60.       function Seek(Offset : longint; Origin : word) : longint; override;
  61.       function Write(const Buffer; Count : longint) : longint; override;
  62.   end;
  63.  
  64.   TaaReadBufferFilter = class(TaaReadFilter)
  65.     {a read-only buffered filter}
  66.     private
  67.       FBuffer : PChar;
  68.       FBufEnd : longint;
  69.       FBufPos : longint;
  70.     protected
  71.       function rbfReadBuffer : boolean;
  72.     public
  73.       constructor Create(aStream : TStream; aSize : longint);
  74.       destructor Destroy; override;
  75.  
  76.       function Read(var Buffer; Count : longint) : longint; override;
  77.       function Seek(Offset : longint; Origin : word) : longint; override;
  78.   end;
  79.  
  80.   TaaWriteBufferFilter = class(TaaWriteFilter)
  81.     {a write-only buffered filter}
  82.     private
  83.       FBuffer : PChar;
  84.       FCurPos : PChar;
  85.     protected
  86.       function wbfWriteBuffer : boolean;
  87.     public
  88.       constructor Create(aStream : TStream);
  89.       destructor Destroy; override;
  90.  
  91.       function Seek(Offset : longint; Origin : word) : longint; override;
  92.       function Write(const Buffer; Count : longint) : longint; override;
  93.   end;
  94.  
  95.   TaaReadTextFilter = class(TaaReadBufferFilter)
  96.     {a read-only text filter}
  97.     private
  98.       FStrBuilder : TaaStringBuilder;
  99.     protected
  100.     public
  101.       constructor Create(aStream : TStream; aSize : longint);
  102.       destructor Destroy; override;
  103.  
  104.       function ReadLine : string; virtual;
  105.       function AtEndOFStream : boolean;
  106.   end;
  107.  
  108.   TaaLineDelimiter = ( {possible line delimiters}
  109.      ldLF,             {..line feed}
  110.      ldCRLF);          {..carriage return line feed}
  111.  
  112.   TaaWriteTextFilter = class(TaaWriteFilter)
  113.     {a write-only text filter}
  114.     private
  115.       FLineDelim : TaaLineDelimiter;
  116.     protected
  117.     public
  118.       constructor Create(aStream : TStream);
  119.  
  120.       procedure WriteLine(const S : string);
  121.  
  122.       property LineDelimiter : TaaLineDelimiter
  123.                   read FLineDelim write FLineDelim;
  124.   end;
  125.  
  126.   TaaDebugFilter = class(TStream)
  127.     {a debug filter}
  128.     private
  129.       FLog    : TaaWriteTextFilter;
  130.       FFile   : TFileStream;
  131.       FStream : TStream;
  132.     protected
  133.       function dfGetOriginStr(aOrigin : word) : string;
  134.     public
  135.       constructor Create(aStream : TStream; const aLogName : string);
  136.       destructor Destroy; override;
  137.  
  138.       function Read(var Buffer; Count : longint) : longint; override;
  139.       function Seek(Offset : longint; Origin : word) : longint; override;
  140.       function Write(const Buffer; Count : longint) : longint; override;
  141.   end;
  142.  
  143.   TaaRegexTextFilter = class(TaaReadTextFilter)
  144.     {a read-only regex text filter}
  145.     private
  146.       FRegexEngine : TaaRegexCompiler;
  147.     protected
  148.     public
  149.       constructor Create(aStream : TStream; aSize : longint;
  150.                    const aRegex : string);
  151.       destructor Destroy; override;
  152.  
  153.       function ReadLine : string; override;
  154.   end;
  155.  
  156.   TaaWindowFilter = class(TStream)
  157.     {a window filter}
  158.     private
  159.       FStream  : TStream;
  160.       FZeroPos : longint;
  161.     protected
  162.     public
  163.       constructor Create(aStream : TStream; aZeroPos : longint);
  164.       destructor Destroy; override;
  165.  
  166.       function Read(var Buffer; Count : longint) : longint; override;
  167.       function Seek(Offset : longint; Origin : word) : longint; override;
  168.       function Write(const Buffer; Count : longint) : longint; override;
  169.   end;
  170.  
  171. implementation
  172.  
  173. const
  174.   BufferSize = 8 * 1024;
  175.  
  176. {===TaaFileStream====================================================}
  177. constructor TaaFileStream.Create(const aFileName : string;
  178.                                        aMode : word);
  179. begin
  180.   FName := aFileName;
  181.   inherited Create(aFileName, aMode);
  182. end;
  183. {====================================================================}
  184.  
  185.  
  186. {===TaaReadFilter====================================================}
  187. constructor TaaReadFilter.Create(aStream : TStream; aSize   : longint);
  188. begin
  189.   Assert(aStream <> nil,
  190.          'TaaReadFilter.Create: the stream cannot be nil');
  191.   inherited Create;
  192.   FStream := aStream;
  193.   if (aSize = -1) then
  194.     FSize := FStream.Size
  195.   else
  196.     FSize := aSize;
  197. end;
  198. {--------}
  199. function TaaReadFilter.Read(var Buffer; Count : longint) : longint;
  200. begin
  201.   Assert(not FGotSizeReq,
  202.          'TaaReadFilter.Read: cannot read whilst getting size');
  203.   Result := FStream.Read(Buffer, Count);
  204. end;
  205. {--------}
  206. function TaaReadFilter.Seek(Offset : longint; Origin : word) : longint;
  207. begin
  208.   case Origin of
  209.     soFromBeginning :
  210.       if FGotSizeReq then begin
  211.         Result := FStream.Position;
  212.         if (Offset = Result) then
  213.           Exit;
  214.         FGotSizeReq := false;
  215.       end;
  216.     soFromCurrent :
  217.       if (Offset = 0) and (not FGotSizeReq) then begin
  218.         Result := FStream.Position;
  219.         Exit;
  220.       end;
  221.     soFromEnd :
  222.       if (Offset = 0) and (not FGotSizeReq) then begin
  223.         Result := FSize;
  224.         FGotSizeReq := true;
  225.         Exit;
  226.       end;
  227.   else
  228.     Assert(false,
  229.        Format('TaaReadFilter.Seek: invalid origin (%d)', [Origin]));
  230.   end;
  231.   Assert(false,
  232.          'TaaReadFilter.Seek: a read-only filter cannot seek');
  233.   Result := 0;
  234. end;
  235. {--------}
  236. function TaaReadFilter.Write(const Buffer; Count : longint) : longint;
  237. begin
  238.   Assert(false,
  239.          'TaaReadFilter.Write: a read-only filter cannot write');
  240.   Result := 0;
  241. end;
  242. {====================================================================}
  243.  
  244.  
  245. {===TaaWriteFilter===================================================}
  246. constructor TaaWriteFilter.Create(aStream : TStream);
  247. begin
  248.   Assert(aStream <> nil,
  249.          'TaaWriteFilter.Create: the stream cannot be nil');
  250.   inherited Create;
  251.   FStream := aStream;
  252. end;
  253. {--------}
  254. function TaaWriteFilter.Read(var Buffer; Count : longint) : longint;
  255. begin
  256.   Assert(false,
  257.          'TaaWriteFilter.Read: a write-only filter cannot read');
  258.   Result := 0;
  259. end;
  260. {--------}
  261. function TaaWriteFilter.Seek(Offset : longint; Origin : word) : longint;
  262. begin
  263.   case Origin of
  264.     soFromBeginning :
  265.       if FGotSizeReq then begin
  266.         Result := FSize;
  267.         if (Offset = Result) then
  268.           Exit;
  269.         FGotSizeReq := false;
  270.       end;
  271.     soFromCurrent :
  272.       if (Offset = 0) and (not FGotSizeReq) then begin
  273.         Result := FSize;
  274.         Exit;
  275.       end;
  276.     soFromEnd :
  277.       if (Offset = 0) and (not FGotSizeReq) then begin
  278.         Result := FSize;
  279.         FGotSizeReq := true;
  280.         Exit;
  281.       end;
  282.   else
  283.     Assert(false,
  284.        Format('TaaWriteFilter.Seek: invalid origin (%d)', [Origin]));
  285.   end;
  286.   Assert(false,
  287.          'TaaWriteFilter.Seek: a read-only filter cannot seek');
  288.   Result := 0;
  289. end;
  290. {--------}
  291. function TaaWriteFilter.Write(const Buffer; Count : longint) : longint;
  292. begin
  293.   Assert(not FGotSizeReq,
  294.          'TaaWriteFilter.Write: cannot write whilst getting size');
  295.   Result := FStream.Write(Buffer, Count);
  296.   inc(FSize, Result);
  297. end;
  298. {====================================================================}
  299.  
  300.  
  301. {===TaaReadBufferFilter==============================================}
  302. constructor TaaReadBufferFilter.Create(aStream : TStream; aSize : longint);
  303. begin
  304.   inherited Create(aStream, aSize);
  305.   GetMem(FBuffer, BufferSize);
  306. end;
  307. {--------}
  308. destructor TaaReadBufferFilter.Destroy;
  309. begin
  310.   if (FBuffer <> nil) then
  311.     FreeMem(FBuffer, BufferSize);
  312.   inherited Destroy;
  313. end;
  314. {--------}
  315. function TaaReadBufferFilter.rbfReadBuffer : boolean;
  316. begin
  317.   {read the next bufferful from the stream}
  318.   FBufEnd := FStream.Read(FBuffer^, BufferSize);
  319.   FBufPos := 0;
  320.   {return true if at least one byte were read, false otherwise}
  321.   Result := FBufEnd <> FBufPos;
  322. end;
  323. {--------}
  324. function TaaReadBufferFilter.Read(var Buffer; Count : longint) : longint;
  325. var
  326.   UserBuf     : PChar;
  327.   BytesToGo   : longint;
  328.   BytesToRead : longint;
  329. begin
  330.   {reference the buffer as a PChar}
  331.   UserBuf := @Buffer;
  332.   {start the counter for the number of bytes read}
  333.   Result := 0;
  334.   {if needed, fill the internal buffer from the underlying stream}
  335.   if (FBufPos = FBufEnd) then
  336.     if not rbfReadBuffer then
  337.       Exit;
  338.   {calculate the number of bytes to copy from the internal buffer}
  339.   BytesToGo := Count;
  340.   BytesToRead := FBufEnd - FBufPos;
  341.   if (BytesToRead > BytesToGo) then
  342.     BytesToRead := BytesToGo;
  343.   {copy the bytes from the internal buffer to the user buffer}
  344.   Move(FBuffer[FBufPos], UserBuf^, BytesToRead);
  345.   {adjust the counters}
  346.   inc(FBufPos, BytesToRead);
  347.   dec(BytesToGo, BytesToRead);
  348.   inc(Result, BytesToRead);
  349.   {while there are more bytes to copy, do so}
  350.   while (BytesToGo <> 0) do begin
  351.     {advance the user buffer}
  352.     inc(UserBuf, BytesToRead);
  353.     {fill the internal buffer from the underlying stream}
  354.     if not rbfReadBuffer then
  355.       Exit;
  356.     {calculate the number of bytes to copy from the internal buffer}
  357.     BytesToRead := FBufEnd - FBufPos;
  358.     if (BytesToRead > BytesToGo) then
  359.       BytesToRead := BytesToGo;
  360.     {copy the bytes from the internal buffer to the user buffer}
  361.     Move(FBuffer^, UserBuf^, BytesToRead);
  362.     {adjust the counters}
  363.     inc(FBufPos, BytesToRead);
  364.     dec(BytesToGo, BytesToRead);
  365.     inc(Result, BytesToRead);
  366.   end;
  367. end;
  368. {--------}
  369. function TaaReadBufferFilter.Seek(Offset : longint;
  370.                                   Origin : word) : longint;
  371. begin
  372.   if (Offset = 0) and (Origin = soFromCurrent) then
  373.     Result := FStream.Position - FBufEnd + FBufPos
  374.   else
  375.     Result := inherited Seek(Offset, Origin);
  376. end;
  377. {====================================================================}
  378.  
  379.  
  380. {===TaaWriteBufferFilter==============================================}
  381. constructor TaaWriteBufferFilter.Create(aStream : TStream);
  382. begin
  383.   inherited Create(aStream);
  384.   GetMem(FBuffer, BufferSize);
  385.   FCurPos := FBuffer;
  386. end;
  387. {--------}
  388. destructor TaaWriteBufferFilter.Destroy;
  389. begin
  390.   if (FBuffer <> nil) then begin
  391.     if (FCurPos <> FBuffer) then
  392.       wbfWriteBuffer;
  393.     FreeMem(FBuffer, BufferSize);
  394.   end;
  395.   inherited Destroy;
  396. end;
  397. {--------}
  398. function TaaWriteBufferFilter.wbfWriteBuffer : boolean;
  399. var
  400.   BytesToWrite : longint;
  401.   BytesWritten : longint;
  402. begin
  403.   BytesToWrite := FCurPos - FBuffer;
  404.   BytesWritten := FStream.Write(FBuffer^, BytesToWrite);
  405.   if (BytesWritten = BytesToWrite) then begin
  406.     Result := true;
  407.     FCurPos := FBuffer;
  408.   end
  409.   else begin
  410.     Result := false;
  411.     if (BytesWritten <> 0) then begin
  412.       Move(FBuffer[BytesWritten], FBuffer^, BytesToWrite - BytesWritten);
  413.       FCurPos := FBuffer + (BytesToWrite - BytesWritten);
  414.     end;
  415.   end;
  416. end;
  417. {--------}
  418. function TaaWriteBufferFilter.Seek(Offset : longint;
  419.                                    Origin : word) : longint;
  420. begin
  421.   if (Offset = 0) and (Origin = soFromCurrent) then
  422.     Result := FStream.Position + (FCurPos - FBuffer)
  423.   else
  424.     Result := inherited Seek(Offset, Origin);
  425. end;
  426. {--------}
  427. function TaaWriteBufferFilter.Write(const Buffer;
  428.                                           Count : longint) : longint;
  429. var
  430.   UserBuf      : PChar;
  431.   BytesToGo    : longint;
  432.   BytesToWrite : longint;
  433. begin
  434.   {reference the buffer as a PChar}
  435.   UserBuf := @Buffer;
  436.   {start the counter for the number of bytes written}
  437.   Result := 0;
  438.   {if needed, empty the internal buffer into the underlying stream}
  439.   if (BufferSize = FCurPos - FBuffer) then
  440.     if not wbfWriteBuffer then
  441.       Exit;
  442.   {calculate the number of bytes to copy to the internal buffer}
  443.   BytesToGo := Count;
  444.   BytesToWrite := BufferSize - (FCurPos - FBuffer);
  445.   if (BytesToWrite > BytesToGo) then
  446.     BytesToWrite := BytesToGo;
  447.   {copy the bytes from the user buffer to the internal buffer}
  448.   Move(UserBuf^, FCurPos^, BytesToWrite);
  449.   {adjust the counters}
  450.   inc(FCurPos, BytesToWrite);
  451.   dec(BytesToGo, BytesToWrite);
  452.   inc(Result, BytesToWrite);
  453.   {while there are more bytes to copy, do so}
  454.   while (BytesToGo <> 0) do begin
  455.     {advance the user buffer}
  456.     inc(UserBuf, BytesToWrite);
  457.     {empty the internal buffer into the underlying stream}
  458.     if not wbfWriteBuffer then
  459.       Exit;
  460.     {calculate the number of bytes to copy to the internal buffer}
  461.     BytesToWrite := BufferSize;
  462.     if (BytesToWrite > BytesToGo) then
  463.       BytesToWrite := BytesToGo;
  464.     {copy the bytes from the user buffer to the internal buffer}
  465.     Move(UserBuf^, FCurPos^, BytesToWrite);
  466.     {adjust the counters}
  467.     inc(FCurPos, BytesToWrite);
  468.     dec(BytesToGo, BytesToWrite);
  469.     inc(Result, BytesToWrite);
  470.   end;
  471. end;
  472. {====================================================================}
  473.  
  474.  
  475. {===TaaReadTextFilter================================================}
  476. constructor TaaReadTextFilter.Create(aStream : TStream; aSize : longint);
  477. begin
  478.   inherited Create(aStream, aSize);
  479.   FStrBuilder := TaaStringBuilder.Create;
  480. end;
  481. {--------}
  482. destructor TaaReadTextFilter.Destroy;
  483. begin
  484.   FStrBuilder.Free;
  485.   inherited Destroy;
  486. end;
  487. {--------}
  488. function TaaReadTextFilter.AtEndOFStream : boolean;
  489. begin
  490.   Result := FSize = Position;
  491. end;
  492. {--------}
  493. function TaaReadTextFilter.ReadLine : string;
  494. const
  495.   CR = ^M;
  496.   LF = ^J;
  497. var
  498.   Ch : char;
  499.   BytesRead : longint;
  500. begin
  501.   {read characters until we get an LF}
  502.   BytesRead := Read(Ch, sizeof(Ch));
  503.   while (BytesRead <> 0) and (Ch <> LF) do begin
  504.     {if it's not a CR character, append it to the current line}
  505.     if (Ch <> CR) then
  506.       FStrBuilder.Add(Ch);
  507.     BytesRead := Read(Ch, sizeof(Ch));
  508.   end;
  509.   {return the string}
  510.   Result := FStrBuilder.AsString;
  511. end;
  512. {====================================================================}
  513.  
  514.  
  515. {===TaaWriteTextFilter===============================================}
  516. constructor TaaWriteTextFilter.Create(aStream : TStream);
  517. begin
  518.   inherited Create(aStream);
  519.   {$IFDEF Win32}
  520.   FLineDelim := ldCRLF;
  521.   {$ENDIF}
  522.   {$IFDEF Linux}
  523.   FLineDelim := ldLF;
  524.   {$ENDIF}
  525. end;
  526. {--------}
  527. procedure TaaWriteTextFilter.WriteLine(const S : string);
  528. const
  529.   cLF : char = ^J;
  530.   cCRLF : array [0..1] of char = ^M^J;
  531. begin
  532.   if (length(S) > 0) then
  533.     Write(S[1], length(S));
  534.   case FLineDelim of
  535.     ldLF   : Write(cLF, sizeof(cLF));
  536.     ldCRLF : Write(cCRLF, sizeof(cCRLF));
  537.   end;
  538. end;
  539. {====================================================================}
  540.  
  541.  
  542. {===TaaDebugFilter===================================================}
  543. constructor TaaDebugFilter.Create(aStream  : TStream;
  544.                             const aLogName : string);
  545. begin
  546.   Assert(aStream <> nil,
  547.          'TaaDebugFilter.Create: the stream cannot be nil');
  548.   inherited Create;
  549.   FStream := aStream;
  550.   FFile := TFileStream.Create(aLogName, fmCreate);
  551.   FLog := TaaWriteTextFilter.Create(FFile);
  552. end;
  553. {--------}
  554. destructor TaaDebugFilter.Destroy;
  555. begin
  556.   FLog.Free;
  557.   FFile.Free;
  558.   inherited Destroy;
  559. end;
  560. {--------}
  561. function TaaDebugFilter.dfGetOriginStr(aOrigin : word) : string;
  562. begin
  563.   case aOrigin of
  564.     soFromBeginning : Result := 'soFromBeginning';
  565.     soFromCurrent   : Result := 'soFromCurrent';
  566.     soFromEnd       : Result := 'soFromEnd';
  567.   else
  568.     Result := Format('Invalid origin [%d]', [aOrigin]);
  569.   end;
  570. end;
  571. {--------}
  572. function TaaDebugFilter.Read(var Buffer; Count : longint) : longint;
  573. begin
  574.   FLog.WriteLine(Format('READ:  Count requested: %d', [Count]));
  575.   Result := FStream.Read(Buffer, Count);
  576.   FLog.WriteLine(Format('       Bytes read: %d', [Result]));
  577. end;
  578. {--------}
  579. function TaaDebugFilter.Seek(Offset : longint; Origin : word) : longint;
  580. var
  581.   OriginStr : string;
  582. begin
  583.   OriginStr := dfGetOriginStr(Origin);
  584.   FLog.WriteLine(Format('SEEK:  Offset: %d, Origin: %s',
  585.                         [Offset, OriginStr]));
  586.   Result := FStream.Seek(Offset, Origin);
  587.   FLog.WriteLine(Format('       Returned position: %d', [Result]));
  588. end;
  589. {--------}
  590. function TaaDebugFilter.Write(const Buffer; Count : longint) : longint;
  591. begin
  592.   FLog.WriteLine(Format('WRITE: Count requested: %d', [Count]));
  593.   Result := FStream.Write(Buffer, Count);
  594.   FLog.WriteLine(Format('       Bytes written: %d', [Result]));
  595. end;
  596. {====================================================================}
  597.  
  598.  
  599. {===TaaRegexTextFilter===============================================}
  600. constructor TaaRegexTextFilter.Create(aStream : TStream;
  601.                                       aSize : longint;
  602.                                 const aRegex : string);
  603. begin
  604.   inherited Create(aStream, aSize);
  605.   FRegexEngine := TaaRegexCompiler.Create(aRegex);
  606. end;
  607. {--------}
  608. destructor TaaRegexTextFilter.Destroy;
  609. begin
  610.   FRegexEngine.Free;
  611.   inherited Destroy;
  612. end;
  613. {--------}
  614. function TaaRegexTextFilter.ReadLine : string;
  615. var
  616.   S : string;
  617. begin
  618.   S := inherited ReadLine;
  619.   while (FRegexEngine.MatchString(S) = 0) do begin
  620.     if AtEndOFStream then begin
  621.       Result := '';
  622.       Exit;
  623.     end;
  624.     S := inherited ReadLine;
  625.   end;
  626.   Result := S;
  627. end;
  628. {====================================================================}
  629.  
  630.  
  631. {===TaaWindowFilter==================================================}
  632. constructor TaaWindowFilter.Create(aStream : TStream; aZeroPos : longint);
  633. begin
  634.   Assert(aStream <> nil,
  635.          'TaaWindowFilter.Create: the stream cannot be nil');
  636.   Assert(aZeroPos >= 0,
  637.          'TaaWindowFilter.Create: the zero position cannot be negative');
  638.   inherited Create;
  639.   FStream := aStream;
  640.   FZeroPos := aZeroPos;
  641.   if (FStream.Position < aZeroPos) then
  642.     FStream.Seek(aZeroPos, soFromBeginning);
  643. end;
  644. {--------}
  645. destructor TaaWindowFilter.Destroy;
  646. begin
  647.   inherited Destroy;
  648. end;
  649. {--------}
  650. function TaaWindowFilter.Read(var Buffer; Count : longint) : longint;
  651. begin
  652.   Result := FStream.Read(Buffer, Count);
  653. end;
  654. {--------}
  655. function TaaWindowFilter.Seek(Offset : longint; Origin : word) : longint;
  656. var
  657.   NewPos : longint;
  658. begin
  659.   case Origin of
  660.     soFromBeginning :
  661.       NewPos := FStream.Seek(Offset + FZeroPos, soFromBeginning);
  662.     soFromCurrent :
  663.       NewPos := FStream.Seek(Offset, soFromCurrent);
  664.     soFromEnd :
  665.       NewPos := FStream.Seek(Offset, soFromEnd);
  666.   else
  667.     Assert(false, 'TaaWindowFilter.Seek: invalid Origin value');
  668.     NewPos := 0;
  669.   end;
  670.  
  671.   if (NewPos < FZeroPos) then
  672.     NewPos := FStream.Seek(FZeroPos, soFromBeginning);
  673.  
  674.   Result := NewPos - FZeroPos;
  675. end;
  676. {--------}
  677. function TaaWindowFilter.Write(const Buffer; Count : longint) : longint;
  678. begin
  679.   Result := FStream.Write(Buffer, Count);
  680. end;
  681. {====================================================================}
  682.  
  683. end.
  684.